package com.zeus.core.config.data;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.zeus.common.constants.ZeusConfigConstant;
import com.zeus.common.enums.ZeusAlarmModelEnum;
import com.zeus.common.log.ZeusLoggerConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;

/**
 * 宙斯配置
 *
 * @author f1ybear_wang  2022/5/5 11:26
 */
public class ZeusConfigDefault extends AbstractZeusConfig {

    private static final Logger logger = LoggerFactory.getLogger(ZeusConfigDefault.class);

    public ZeusConfigDefault() {
        super();
    }

    /**
     * 初始化配置
     *
     * @author wangfeixiong126@gmail.com  2021/5/21 23:10
     */
    @Override
    void init() {
        synchronized (this) {
            if (this.inited) {
                return;
            }
            try {
                // 初始化配置
                loadConfig();

                if (logger.isInfoEnabled() && ZeusLoggerConfig.needEnableLogger()) {
                    logger.info("### Zeus报警服务, 加载配置信息完成");
                }
                this.inited = true;
            } catch (Throwable e) {
                if (logger.isWarnEnabled() && ZeusLoggerConfig.needEnableLogger()) {
                    logger.warn("### Zeus报警服务, 加载配置出现异常 >> errMsg = {}", e.getMessage());
                }
            }
        }
    }

    @Override
    public void doRefresh() {
        // 初始化配置
        this.loadConfig();

        // 通知下有更新配置
        super.sendConfigChangeEvent();
    }


    /**
     * 加载配置信息
     *
     * @author wangfeixiong126@gmail.com  2021/7/1 20:24
     */
    private void loadConfig() {
        if (!checkConfigSource()) {
            if (logger.isWarnEnabled() && ZeusLoggerConfig.needEnableLogger()) {
                logger.warn("### 宙斯相关配置服务初始化失败！");
            }
            return;
        }
        // 基础配置
        final ZeusConfig.BaseConfig baseConfig = loadBaseConfig();

        // 级别规则配置
        final List<ZeusConfig.AlarmLevelRule> alarmLevelRules = loadLevelRuleConfig();

        // 超级配置
        final ZeusConfig.SuperConfig superConfig = loadSuperConfig();

        // 规则2
        final ZeusConfig.Rule2Threshold rule2Threshold = loadRule2Config();

        // 加载日志配置
        loadLogConfig(baseConfig);

        // 配置初始化
        ZeusConfig.ConfigData alarmConfigInfo = new ZeusConfig.ConfigData();
        alarmConfigInfo.setBaseConfig(baseConfig);
        alarmConfigInfo.setAlarmLevelRuleList(alarmLevelRules);
        alarmConfigInfo.setSuperConfig(superConfig);
        alarmConfigInfo.setRule2Threshold(rule2Threshold);

        if (logger.isInfoEnabled() && ZeusLoggerConfig.needEnableLogger()) {
            logger.info(">>> Zeus报警服务, 获取配置信息 >> alarmConfigInfo = {}", alarmConfigInfo);
        }

        // 赋值
        alarmConfig = alarmConfigInfo;
    }

    /**
     * 加载聚合规则2阈值
     *
     * @return ZeusConfig.Rule2Threshold 聚合规则2-阈值
     * @author f1ybear_wang  2022/3/1 3:35 下午
     */
    private ZeusConfig.Rule2Threshold loadRule2Config() {
        ZeusConfig.Rule2Threshold threshold = null;
        try {
            String thresholdStr = getProperty(ZeusConfigConstant.Key.RULE2_THRESHOLD);
            if (thresholdStr != null && !thresholdStr.isEmpty()) {
                threshold = new Gson().fromJson(thresholdStr, ZeusConfig.Rule2Threshold.class);
            }
        } catch (Throwable t) {
            if (logger.isWarnEnabled() && ZeusLoggerConfig.needEnableLogger()) {
                logger.warn("### Zeus报警服务, 加载报警级别规则失败 >> errMsg = {}", t.getMessage());
            }
        }
        if (threshold == null) {
            threshold = new ZeusConfig.Rule2Threshold();
        }

        // 时间
        if (threshold.getTime() == null) {
            threshold.setTime(ZeusConfigConstant.DefaultValue.DEFAULT_RULE2_THRESHOLD_TIME);
        }
        // 阈值
        if (threshold.getNumber() == null) {
            threshold.setNumber(ZeusConfigConstant.DefaultValue.DEFAULT_RULE2_THRESHOLD_NUMBER);
        }

        return threshold;
    }

    /**
     * 加载基础配置
     *
     * @return ZeusConfig.BaseConfig 基础配置
     * @author f1ybear_wang  2022/2/21 6:32 下午
     */
    private ZeusConfig.BaseConfig loadBaseConfig() {
        ZeusConfig.BaseConfig baseConfig = new ZeusConfig.BaseConfig();

        // 是否开启报警
        baseConfig.setEnabled(
            Boolean.parseBoolean(getProperty(ZeusConfigConstant.Key.Base.MONITOR_ENABLED, Boolean.FALSE.toString())));

        // 模式
        String model = getProperty(ZeusConfigConstant.Key.Base.MONITOR_MODEL);
        baseConfig.setModel(Optional.ofNullable(ZeusAlarmModelEnum.parse(model)).orElse(ZeusAlarmModelEnum.NORMAL));

        // 默认钉钉机器人
        baseConfig.setDingTalkList(getDefaultDingTalkList());

        // 黑名单
        baseConfig.setBackList(getPropertySet(ZeusConfigConstant.Key.Base.LOG_MONITOR_BACK_LIST));

        // 错误信息字符串长度
        baseConfig.setMessageLength(getAlarmImportInfoLength(ZeusConfigConstant.Key.Base.MONITOR_MESSAGE_LENGTH,
            ZeusConfigConstant.DefaultValue.DEFAULT_MESSAGE_LENGTH));

        // 异常字符串长度
        baseConfig.setExceptionLength(getAlarmImportInfoLength(ZeusConfigConstant.Key.Base.MONITOR_EXCEPTION_LENGTH,
            ZeusConfigConstant.DefaultValue.DEFAULT_EXCEPTION_LENGTH));

        // 堆栈字符串长度
        baseConfig.setStackLength(getAlarmImportInfoLength(ZeusConfigConstant.Key.Base.MONITOR_STACK_LENGTH,
            ZeusConfigConstant.DefaultValue.DEFAULT_STACK_LENGTH));

        // ELK中索引名称
        baseConfig.setElkUrl(getProperty(ZeusConfigConstant.Key.Base.MONITOR_ELK_URL));

        // 日志打印是否开启
        baseConfig.setLogPrintEnable(Boolean
            .parseBoolean(getProperty(ZeusConfigConstant.Key.Base.MONITOR_LOG_PRINT_ENABLED, Boolean.TRUE.toString())));

        // 服务启动通知是否开启
        baseConfig.setStartNotifyEnable(Boolean
            .parseBoolean(getProperty(ZeusConfigConstant.Key.Base.START_NOTIFY_ENABLED, Boolean.TRUE.toString())));

        // 服务关闭通知是否开启
        baseConfig.setShutdownNotifyEnabled(Boolean
            .parseBoolean(getProperty(ZeusConfigConstant.Key.Base.SHUTDOWN_NOTIFY_ENABLED, Boolean.TRUE.toString())));

        // 应用名称
        baseConfig.setApplicationName(getProperty(ZeusConfigConstant.Key.Base.APPLICATION_NAME));

        // 环境
        baseConfig.setSpringProfilesActive(getProperty(ZeusConfigConstant.Key.Base.SPRING_PROFILES_ACTIVE));
        return baseConfig;
    }

    /**
     * 加载报警级别规则配置
     *
     * @return List<ZeusConfig.AlarmLevelRule> 报警级别规则配置列表
     * @author f1ybear_wang  2022/2/21 6:36 下午
     */
    private List<ZeusConfig.AlarmLevelRule> loadLevelRuleConfig() {
        try {
            String alarmLevelRuleStr = getProperty(ZeusConfigConstant.Key.MONITOR_ALARM_LEVEL_RULE);
            if (alarmLevelRuleStr != null && !alarmLevelRuleStr.isEmpty()) {
                return new Gson().fromJson(alarmLevelRuleStr,
                    new TypeToken<List<ZeusConfig.AlarmLevelRule>>() {}.getType());
            }
        } catch (Throwable t) {
            if (logger.isWarnEnabled() && ZeusLoggerConfig.needEnableLogger()) {
                logger.warn("### Zeus报警服务, 加载报警级别规则失败 >> errMsg = {}", t.getMessage());
            }
        }
        return new ArrayList<>();
    }

    /**
     * 加载超级配置
     *
     * @return ZeusConfig.SuperConfig 超级配置
     * @author f1ybear_wang  2022/2/21 6:39 下午
     */
    private ZeusConfig.SuperConfig loadSuperConfig() {
        ZeusConfig.SuperConfig superConfig = new ZeusConfig.SuperConfig();

        String enabled = getProperty(ZeusConfigConstant.Key.Super.SUPER_MONITOR_ENABLED);
        if (enabled != null && !enabled.isEmpty()) {
            // 是否开启报警
            superConfig
                .setEnabled(Boolean.parseBoolean(getProperty(ZeusConfigConstant.Key.Super.SUPER_MONITOR_ENABLED)));
        }

        // 模式
        String model = getProperty(ZeusConfigConstant.Key.Super.SUPER_MONITOR_MODEL);
        if (model != null && !model.isEmpty()) {
            superConfig.setModel(Optional.ofNullable(ZeusAlarmModelEnum.parse(model)).orElse(null));
        }

        // 黑名单
        superConfig.setBackList(getPropertySet(ZeusConfigConstant.Key.Super.SUPER_LOG_MONITOR_BACK_LIST));
        return superConfig;
    }

    /**
     * 加载日志配置
     *
     * @param baseConfig 基础配置
     * @author f1ybear_wang  2022/2/21 6:39 下午
     */
    private void loadLogConfig(ZeusConfig.BaseConfig baseConfig) {
        // 设置配置
        ZeusLoggerConfig.needEnableLogger(baseConfig.getLogPrintEnable());
    }

    /**
     * 获取默认钉钉机器人列表
     *
     * @return 钉钉机器人列表
     * @author wangfeixiong126@gmail.com  2021/6/29 20:15
     */
    private List<ZeusConfig.DingTalkInfo> getDefaultDingTalkList() {
        try {
            String dingTalkStr = getProperty(ZeusConfigConstant.Key.Base.MONITOR_DING_TALK);
            if (dingTalkStr != null && !dingTalkStr.isEmpty()) {
                // 字符串转对象
                return new Gson().fromJson(dingTalkStr, new TypeToken<List<ZeusConfig.DingTalkInfo>>() {}.getType());
            }
        } catch (Exception e) {
            if (logger.isWarnEnabled() && ZeusLoggerConfig.needEnableLogger()) {
                logger.warn("### Zeus报警服务, 加载默认钉钉机器人列表失败 >> errMsg = {}", e.getMessage());
            }
        }
        return new ArrayList<>();
    }

    /**
     * 获取报警重要信息配置长度
     *
     * @param key           配置key
     * @param defaultLength 默认长度
     * @return Integer 长度
     * @author wangfeixiong126@gmail.com  2021/6/29 19:56
     */
    private Integer getAlarmImportInfoLength(String key, Integer defaultLength) {
        try {
            String length = getProperty(key);
            if (length != null && !length.isEmpty()) {
                return Integer.valueOf(length.trim());
            }
        } catch (Exception e) {
            if (logger.isWarnEnabled() && ZeusLoggerConfig.needEnableLogger()) {
                logger.warn("### Zeus报警服务, 获取报警配置中信息最大长度出现异常 >> errMsg = {}", e.getMessage());
            }
        }
        return defaultLength;
    }

    /**
     * 获取配置中的set内容
     *
     * @param key 键
     * @return Set内容
     * @author f1ybear_wang  2022/3/29 4:25 下午
     */
    private Set<String> getPropertySet(String key) {
        try {
            if (key == null || key.isEmpty()) {
                return new HashSet<>();
            }
            String setStr = getProperty(key);
            if (setStr == null || setStr.isEmpty()) {
                return new HashSet<>();
            }
            return new Gson().fromJson(setStr, new TypeToken<Set<String>>() {}.getType());
        } catch (Exception e) {
            if (logger.isWarnEnabled() && ZeusLoggerConfig.needEnableLogger()) {
                logger.warn("### Zeus报警服务, 加载Set数据出现异常 >> key = {}, errMsg = {}", key, e.getMessage());
            }
            return new HashSet<>();
        }
    }

}
